#ifndef __CANYON_CORE_ARCH
#define __CANYON_CORE_ARCH

#include <cstdint>

typedef uintmax_t size_t;

namespace canyon{

/* typedef uint8_t regid_t
 *
 * THIS TYPEDEF CANNOT BE CHANGED!
 * IF CHANGE THIS, IT WILL INFLUENCE 'instructions' and 'command_config'!
 */
typedef uint8_t regid_t;
typedef uint8_t code_t;

/* const size_t REGISTER_SIZE => 64bits
 *
 * THIS CONSTANT CANNOT BE CHANGED!
 * IF CHANGE THIS, IT WILL INFLUENCE
 * 'instructions' in `instructions.hpp`
 * and 'RegPointer' in `pointer.hpp`!
 */
constexpr size_t REGISTER_SIZE = 8;
constexpr size_t MEMORY_SIZE   = 1*1024*1024;  // 1MB

struct __attribute__((packed)) command_regs{
    regid_t reg1;
    regid_t reg2;
};

struct __attribute__((packed)) command_data_bytes{
    /* HERE IS FOR LITTLE-ENDIAN */
    /* can be change by the total size of command_data,
       but must at least equal or lower than the total size */
    uint8_t b0;
    uint8_t b1;
};

union command_data{
    uint16_t           data16;
    command_data_bytes data8;
};

union command_config{
    command_data data;
    command_regs regs;
};

struct __attribute__((packed)) command{
    code_t         code;
    command_config config;
};

enum reg : regid_t{
    EMPTY,
    CODE,
    IVAL,
    ALU,
    ADR,
    DEV,
    RET,
    R0,
    R1,
    R2,
    R3,
    R4,
    R5,
    R6,
    R7,
    R8,
    R9,
    R10,
    R11,
    R12,
    R13,
    R14,
    R15,
    R16,
    end
};

}

#endif
